package com.corpgovernment.common.utils;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.*;

public class ObjectUtils {
    /**
     * @Author: majl
     * @Date: 2019-5-20
     * @Description: model 转 add
     */
    public static  <T> T copyProperties(Object sourceObj, Class<T> targetClass) {
        try {
            if (sourceObj == null) {
                return null;
            }
            Map<String, Method> sourceMethods = getReadMethod(sourceObj.getClass());//以后可做缓存提高效率
            T targetObj = targetClass.newInstance();
            Method[] targetMethods = targetClass.getMethods();
            for (Method writeMethod : targetMethods) {
                if (writeMethod.getParameterTypes().length != 1) {
                    continue;
                }
                if (writeMethod.getName().startsWith("set")) {
                    Method readMethod = sourceMethods.get("get" + writeMethod.getName().substring(3));
                    if (readMethod == null) {
                        continue;
                    }
                    try {
                        Object returnObj = readMethod.invoke(sourceObj);
                        if (returnObj == null) {
                            continue;
                        }
                        if (String.class.equals(readMethod.getReturnType()) && String.class.equals(writeMethod.getParameterTypes()[0])) {
                            writeMethod.invoke(targetObj, returnObj);
                        }
                        if (Integer.class.equals(readMethod.getReturnType()) && Integer.class.equals(writeMethod.getParameterTypes()[0])) {
                            writeMethod.invoke(targetObj, returnObj);
                        }
                        if (Long.class.equals(readMethod.getReturnType()) && Long.class.equals(writeMethod.getParameterTypes()[0])) {
                            writeMethod.invoke(targetObj, returnObj);
                        }
                        if (BigDecimal.class.equals(readMethod.getReturnType()) && BigDecimal.class.equals(writeMethod.getParameterTypes()[0])) {
                            writeMethod.invoke(targetObj, returnObj);
                        }
                        if (Date.class.equals(readMethod.getReturnType()) && writeMethod.getParameterTypes().length == 1) {
                            //Date转String
                            if (String.class.equals(writeMethod.getParameterTypes()[0])) {
                                writeMethod.invoke(targetObj, DateUtil.dateToString((Date) returnObj));
                            } else if (Date.class.equals(writeMethod.getParameterTypes()[0])) {
                                writeMethod.invoke(targetObj, returnObj);
                            }

                        }
                        //暂时约定vo对象里面的list放的对象只能是自己 以后可用注解方式表明list存放的类类型
                        if (List.class.equals(readMethod.getReturnType())) {
                            List returnList = (List) returnObj;
                            if (returnList.size() == 0) {
                                continue;
                            }
                            List voList = ListUtils.copyList(returnList, targetClass);
                            writeMethod.invoke(targetObj, voList);
                        }
                        if (Boolean.class.equals(readMethod.getReturnType()) && Boolean.class.equals(writeMethod.getParameterTypes()[0])) {
                            writeMethod.invoke(targetObj, returnObj);
                        }
                    } catch (Exception e) {
                    }
                }
            }
            return targetObj;
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * @Author: majl
     * @Date: 2019-5-20
     * @Description: modelList 转 voList
     */
    public List copyList(List sourceList, Class targetClass) {
        List list = new ArrayList();
        for (Object sourceObj : sourceList) {
            Object obj = copyProperties(sourceObj, targetClass);
            list.add(obj);
        }
        return list;
    }

    private static Map<String, Method> getReadMethod(Class c) {
        Map<String, Method> map = new HashMap<>();
        for (Method m : c.getMethods()) {
            if (m.getName().startsWith("get")) {
                map.put(m.getName(), m);
            }
        }
        return map;
    }
}
